/*=============================================================================

  SONY CAM HAL MODULE

  FILE: hw_sony_cam_echo.c
  
  DESCRIPTION

    SONY CAM HAL Module

  Copyright (c) DaeSung Engineering Inc. All rights reserved.

=============================================================================*/
/*=============================================================================

  EDIT HISTORY

  ---------  -------  -------------------------------------------------------
    when        who          what, where, why
  ---------  -------  -------------------------------------------------------
   13/10/15   jyko         Initial version

=============================================================================*/

#include "hw_sony_cam_mod.h"
#include <stdio.h>
#include <string.h>
#include <math.h>

/*=============================================================================
  CONSTANT DEFINITIONS
=============================================================================*/
#define		GEN_INTERVAL	(20)

/*=============================================================================
  STRUCTURE DEFINITION
=============================================================================*/
typedef struct
{
	mcxt		task;
	mcxt		timer;
	word		dummy;
} cam_emul_s;

/*=============================================================================
  EXTERNALIZED FUNCION DEFINITION
=============================================================================*/
void cam_emulTimerCallback(mcxt pCxt, void *pUsrCxt);
dword __stdcall cam_emul_task(void *ptr);

//-------------------------------------------------------------------
// INITIALIZATION & TERMINATION
//-------------------------------------------------------------------
boolean cam_InitializeEMUL(mcxt dev, byte comPort, byte baudRate, int32 waitTime)
{
	cam_s			*cam = CAMMOD(dev); 
	cam_emul_s		*em;

	em = (cam_emul_s*)memCalloc(sizeof(*em));
	cam->em_cxt = em;

	// Timer
	em->timer = Timer_Alloc();
	
	// Task
	em->task = Task_Alloc();
	Task_Create(em->task, cam_emul_task, dev);
	
	CAMERR_CLEAR(cam);

	return	TRUE;
}

boolean cam_TerminateEMUL(mcxt dev)
{
	cam_s			*cam = CAMMOD(dev);
	cam_emul_s		*em = CAMEMUL(dev);
	
	if(cam == NULL)
		return	FALSE;

	if(em->timer)
	{
		Timer_Kill(em->timer);
		Timer_Free(em->timer);
		em->timer = NULL;
	}
	
	if(em->task)
	{
		Task_Destroy(em->task);
		Task_Free(em->task);
		em->task = NULL;
	}
	memFree(em);

	cam->em_cxt = NULL;
	
	CAMERR_CLEAR(cam);

	return	TRUE;
}


//---------------------------------------------------------
// CONFIGURATION
//---------------------------------------------------------
// ADVANCED
boolean cam_CFGEXsetEMUL(mcxt dev, CAM_CFGEX_s *cfg)
{
	cam_s		*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;
	
	if(cfg == NULL)
	{
		CAMERR_SET(CAMMOD(dev), CAM_PARAM_EC); 
		return	FALSE;
	}

	memCopy(&cam->cfg_ex, cfg, sizeof(*cfg));

	return	TRUE;
}

// SAVE TO DEVICE
boolean cam_CFGSaveEMUL(mcxt dev)
{
	cam_s		*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;
	
	return	TRUE;
}

//---------------------------------------------------------
// SETUP
//---------------------------------------------------------
boolean cam_GAINsetEMUL(mcxt dev, int32 gain)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.gain = gain;

	return	TRUE;
}

boolean cam_SHUTTERsetEMUL(mcxt dev, int32 sht)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.exp_time = sht;

	return	TRUE;
}

boolean cam_WBsetEMUL(mcxt dev, int32 mod)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.wbmod = (byte)mod;

	return	TRUE;
}

boolean cam_RGAINsetEMUL(mcxt dev, int32 rgain)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.rgain = rgain;

	return	TRUE;
}

boolean cam_BGAINsetEMUL(mcxt dev, int32 bgain)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.bgain = bgain;

	return	TRUE;
}

boolean cam_WBWsetEMUL(mcxt dev, int32 enable)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.wbdisp = (boolean)enable;

	return	TRUE;
}

boolean cam_SHARPsetEMUL(mcxt dev, int32 shp)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.sharp = shp;

	return	TRUE;
}

boolean cam_GAMsetEMUL(mcxt dev, int32 mod)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.gamma = (byte)mod;

	return	TRUE;
}

boolean cam_BINsetEMUL(mcxt dev, int32 val)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.bin = val;

	return	TRUE;
}

boolean cam_COLBARsetEMUL(mcxt dev, int32 enable)	// for XCL-U1000C only
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.colbar = (boolean)enable;

	return	TRUE;
}

boolean cam_BRTsetEMUL(mcxt dev, int32 brt)
{
	cam_s			*cam = CAMMOD(dev);

	if(cam == NULL)
		return	FALSE;

	cam->cfg_ex.brate = (byte)brt;

	return	TRUE;
}

//---------------------------------------------------------
// TRIGGER MODE
//---------------------------------------------------------
boolean cam_TRIGsetEMUL(mcxt dev, int32 mode/*CAM_TRIGGER*/)
{
	cam_s		*cam = CAMMOD(dev);
	byte			prev;
	
	if(cam == NULL)
		return	FALSE;

	if(cam->com == NULL)
	{
		CAMERR_SET(cam, CAM_INIT_EC);
		return	FALSE;
	}
	
	prev = cam->cfg_ex.trigmod;
	
	switch(mode)
	{
	case CAM_EDGE_TRIG:
	case CAM_WIDTH_TRIG:
	case CAM_NONE_TRIG:
	{
		break;
	}
	default:
	{
		CAMERR_SET(cam, CAM_PARAM_EC); 
		return	FALSE;
	}
	}
	cam->cfg_ex.trigmod = (byte)mode;
	
	return	TRUE;
}

#define CAM_EMUL_DAQ_SIG			(TASK_SIG_CUSTOM)
dword __stdcall cam_emul_task(void *ptr)
{
	cam_s		*cam = (cam_s*)ptr;
	cam_emul_s	*em = CAMEMUL(cam);
	mcxt		tcb;
	dword		sig;
	
	tcb = em->task;

	while(TRUE)
	{
		//DBGPRINT("T%d ", cam->devID);
		sig = Task_GetSignal(tcb);

		if(TASK_IS_STARTREQ(sig))
		{
			Task_StartACK(tcb);
		}
		if(TASK_IS_STOPREQ(sig))
		{
			Task_StopACK(tcb);
			break;
		}
		if(TASK_SIGNAL_ENABLED(sig, CAM_EMUL_DAQ_SIG))
		{
			TASK_CLEAR_SIGNAL(tcb, CAM_EMUL_DAQ_SIG);
		}
	}

	return	(0);
}

void cam_emulTimerCallback(mcxt pCxt, void *pUsrCxt)
{
	cam_s		*cam = (cam_s*)pUsrCxt;
	cam_emul_s	*em;

	if(cam == NULL)
	{
		Timer_Kill(pCxt);
		return;
	}
	
	em = CAMEMUL(cam);

	if(em == NULL)
	{
		Timer_Kill(pCxt);
	}

	Task_PutSignal(em->task, CAM_EMUL_DAQ_SIG);
}
